﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Core
{
    public class CodeTypes : Entity, IAwake<Assembly[]>
    {
        private Dictionary<string, Type> allTypes = new Dictionary<string, Type>();
        private Dictionary<Type, Dictionary<string,Type>> types = new Dictionary<Type, Dictionary<string, Type>>();
        void IAwake<Assembly[]>.Awake(Assembly[] assemblies)
        {
            foreach((string typeName, Type type) in GetTypes(assemblies))
            {
                if (type.IsAbstract)
                    continue;

                allTypes[typeName] = type;

                object[] objects = type.GetCustomAttributes(typeof(BaseAttribute), true);

                foreach (var o in objects)
                {
                    var oType = o.GetType();
                    if(!types.TryGetValue(oType, out var _types))
                    {
                        _types = new Dictionary<string, Type>();
                        types[oType] = _types;
                    }

                    _types[type.Name] = type;
                }
            }
        }

        public Dictionary<string, Type> GetTypes(Type type)
        {
            if(!types.ContainsKey(type))
            {
                return new Dictionary<string, Type>();
            }
            return types[type];
        }

        public Type GetType(string typeName)
        {
            allTypes.TryGetValue(typeName, out var type);
            return type;
        }

        public Type GetType(Type type, string typeName)
        {
            var typeDict = GetTypes(type);
            typeDict.TryGetValue(typeName, out var result);
            return result;
        }

        Dictionary<string, Type> GetTypes(Assembly []assembly)
        {
            Dictionary<string, Type> types = new Dictionary<string, Type>();

            foreach (Assembly ass in assembly)
            {
                foreach (Type type in ass.GetTypes())
                {
                    types[type.FullName] = type;
                }
            }

            return types;
        }

    }
}